<!--
formConfig配置form表单的配置文件
  labelWidth 表单的宽度
  itemStyle  每个el-form-item的样式
  colLayout  利用element的el-row来实现弹性布局
  headerTitle 表单表头
  btnConfig  搜索按钮等配置
 -->

<template>
  <div class="form">
    <el-form :model="formData" :label-width="labelWidth">
      <div class="header">
        <span>{{ headerTitle }}</span>
      </div>
      <el-row>
        <template v-for="form in formConfig" :key="form.label">
          <el-col :span="8" v-bind="colLayout">
            <!-- isHidden：false为显示密码输入框  true不显示 可选填 -->
            <el-form-item
              v-if="!form.isHidden"
              :label="form.label"
              :style="itemStyle"
              :rules="form.rules"
            >
              <template v-if="form.type === 'input' || form.type === 'password'">
                <el-input
                  :placeholder="form.placeholder"
                  :show-password="form.type === 'password'"
                  v-model="formData[`${form.field}`]"
                />
                <!--
                  不使用v-model语法糖的写法
                  :model-value="modelValue[form.field]"
                  @update:model-value="handlerModelValue($event, form.field)"
                   -->
              </template>
              <template v-if="form.type === 'select'">
                <el-select :placeholder="form.placeholder" v-model="formData[`${form.field}`]">
                  <el-option
                    v-for="option in form.options"
                    :key="option.value"
                    :value="option.value"
                    :label="option.label"
                  ></el-option>
                </el-select>
              </template>
              <template v-if="form.type === 'datepicker'">
                <el-date-picker
                  type="daterange"
                  :start-placeholder="form.otherOptions.startPlaceholder"
                  :end-placeholder="form.otherOptions.endPlaceholder"
                  :default-value="form.otherOptions.defaultDateValue"
                  :value-format="form.otherOptions.format"
                  v-model="formData[`${form.field}`]"
                />
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
      <div class="footer">
        <template v-for="item in btnConfig" :key="item.btnText">
          <el-button
            v-if="item.show"
            :type="(item.type as any)"
            :icon="(ElIconFn as any)[item.icon]"
            @click="handleClick(item.btnText)"
            >{{ item.btnText }}</el-button
          >
        </template>
      </div>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { watch, ref } from 'vue'
import { IFormItem, Ibtn } from '../types/index'
import * as ElIconFn from '@element-plus/icons-vue'

interface Props {
  // 给props设置一个接口 props中需要一个formConfig字段 此字段的类型是IFormItem数组类型
  formConfig: IFormItem[]
  labelWidth: string
  itemStyle?: any
  colLayout?: any
  headerTitle?: string
  btnConfig: Ibtn[]
  modelValue: any
  footerHeight?: string
}
const props = withDefaults(defineProps<Props>(), {
  formConfig: () => [],
  labelWidth: 'auto',
  itemStyle: () => ({
    padding: '8px 40px'
  }),
  colLayout: () => ({
    xl: 6, //>1920 展示4个
    lg: 8, //≥1200px 展示3个
    md: 12, //≥992px 展示2个
    sm: 24, //≥768px 展示一个
    xs: 24 //<=768px 展示一个
  }),
  footerHeight: '40px'
})

const emit = defineEmits(['update:modelValue', 'click'])
const formData = ref({ ...props.modelValue }) //浅拷贝  监听formData改变 抛出

watch(
  formData,
  (newValue) => {
    console.log(newValue, 'formData')
    emit('update:modelValue', newValue)
  },
  { deep: true }
)
const handleClick = (type: string) => {
  emit('click', type)
}

//todo 不使用v-model语法糖的写法 直接绑定modelValue和 @update:model-value
/* const handlerModelValue = (value: any, field: string) => {
  console.log({ ...props.modelValue, [field]: value })
  emit('update:modelValue', { ...props.modelValue, [field]: value })
} */
</script>

<style lang="less" scoped>
.form {
  .header {
    display: flex;
    justify-content: center;
  }
  .footer {
    height: v-bind(footerHeight);
    display: flex;
    justify-content: flex-end;
    padding: 0 8px 5px 0;
  }
}
</style>
